package com.jie.netty.clinet.sender;

import cn.hutool.core.collection.CollectionUtil;
import com.jie.constant.IMRedisKey;
import com.jie.constant.IMTerminalType;
import com.jie.enums.IMCmdType;
import com.jie.enums.IMSendCode;
import com.jie.netty.model.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

import static com.jie.constant.IMRabbitMqKey.*;

@Service
public class IMSender {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送单聊信息
     * @param message
     * @param <T>
     */
    public<T> void sendPrivateMessage(IMPrivateMessage<T> message) {
        //推送多端 现在只有web端 模拟
        for (Integer terminal : message.getRecvTerminals()) {
            // 获取对方连接的channelId
            String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, message.getRecvId().toString(), terminal.toString());
            Integer serverId = (Integer)redisTemplate.opsForValue().get(key);
            //判断对方是否在线
            if (serverId != null) {
                IMRecvInfo recvInfo = new IMRecvInfo();
                recvInfo.setMessageId(message.getMessageId());
                recvInfo.setCmd(IMCmdType.PRIVATE_MESSAGE.code());
                recvInfo.setSendResult(message.getSendResult());
                recvInfo.setSender(message.getSender());
                recvInfo.setReceivers(Collections.singletonList(new IMUserInfo(message.getRecvId(),terminal)));
                recvInfo.setData(message.getData());
                //在线推送给mq类进行消费
                rabbitTemplate.convertAndSend(CHAT_EXCHANGE,PRIVATE,recvInfo);
            } else if (message.getSendResult()) {
                // 回复消息状态 对方未在线的情况
                IMSendResult result = new IMSendResult();
                result.setSender(message.getSender());
                result.setReceiver(new IMUserInfo(message.getRecvId(), terminal));
                result.setCode(IMSendCode.NOT_ONLINE.code());
                result.setData(message.getData());

            }
            // TODO 推送给自己的其他终端
        }

    }

    /**
     * TODO 发送群聊信息
     * @param message
     * @param <T>
     */
    public<T> void sendGroupMessage(IMGroupMessage<T> message) {

    }

    public Map<Long,List<IMTerminalType>> getOnlineTerminal(List<Long> userIds){
        if(CollectionUtil.isEmpty(userIds)){
            return Collections.EMPTY_MAP;
        }
        // 把所有用户的key都存起来
        Map<String, IMUserInfo> userMap = new HashMap<>();
        for(Long id:userIds){
            for (Integer terminal : IMTerminalType.codes()) {
                String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, id.toString(), terminal.toString());
                userMap.put(key,new IMUserInfo(id,terminal));
            }
        }
        // 批量拉取
        List<Object> serverIds = redisTemplate.opsForValue().multiGet(userMap.keySet());
        int idx = 0;
        Map<Long,List<IMTerminalType>> onlineMap = new HashMap<>();
        for (Map.Entry<String,IMUserInfo> entry : userMap.entrySet()) {
            // serverid有值表示用户在线
            if(serverIds.get(idx++) != null){
                IMUserInfo userInfo = entry.getValue();
                List<IMTerminalType> terminals = onlineMap.computeIfAbsent(userInfo.getId(), o -> new LinkedList<>());
                terminals.add(IMTerminalType.fromCode(userInfo.getTerminal()));
            }
        }
        // 去重并返回
        return onlineMap;
    }

    /**
     * 判断用户是否在线
     * @param userId
     * @return Boolean
     */
    public Boolean isOnline(Long userId) {
        String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, userId.toString(), "*");
        return !redisTemplate.keys(key).isEmpty();
    }

    /**
     * 判断多组用户是否在线
     * @param userIds
     * @return
     */
    public List<Long> getOnlineUser(List<Long> userIds){
        return new LinkedList<>(getOnlineTerminal(userIds).keySet());
    }
}
